This is the plot of MyCameraCentral and the relationship between the Camera driver itself and the client: Consider this as a combined camera database and factory. A client first instantiates a CameraCentral and sets itself as its delegate (the client only has ONE CameraCentral - it's a singleton although this is not enforced but results will be probably terrible if you don't do so). Then the client calls [startup]. This will do two things: First, it will look through all available camera types and ask them for their usb signature (type/vendor id). After that, the USB notification process is started.
If a new camera is detected and the device matches one of the camera types, the delegate will be notified by [cameraDetected] with an unique number identifying the camera. The delegate may now reply by using [useCamera] with the id received by the delegate method. If everything is fine, will get a ready-to-use CameraDriver object for the camera - with the delegate already set to the client. But you can change the delegate if you wish. It is also kept in a list of active cameras by the camera centrral.
If a camera is unplugged, the camera central will detect this and look in its list of active cameras if that camera is currently in use. If yes, the central will [shutdown] the camera, which will notify the client about it by calling the delegate's [cameraHasShutDown]. This indicates the client that the camera driver object is finished and can be released by the client. The camera will also notify its center about the [shutdown] which will remove the driver from the list of active drivers and release that object.
The benefit of this is that client may also simply [shutdown] the camera. It will behave identical to the cameraHasShutDown procedure. The only difference is that the camera central will know that it hasn't been really unplugged and keep the camera in its list of available cameras which can be browsed.
The way for the client to shut everything down is to call the camera central's [shutdown]. This will stop the notification process and shut down all cameras.
Note that in older versions, there was a dedicated thread for the USB plugging notification stuff: wiringThread. Unfortunately, this mechanism conflicted with some other applications (since this thread will also be started when macam is used as a QuickTime VDIG component and the component will start the thread in all cases - no matter if the application actually uses a VDIG - and some applications had problems with threads that were not caused by them). So all the functionality was put into the main thread.
*/
@interface MyCameraCentral : NSObject {
NSMutableArray* cameraTypes; //A list of dictionaries containing long "vendorID", long "productID" and class "class"
NSMutableArray* cameras; //A list of cameras currently connected
/* Why is this ana array and not a dictionary keyed by cid? This will make enumeration simpler - if we implement browsing in the cameras later. On the other hand, finding a cam by cid now requires walking through the array. That's not too bad since that array will probably never be so big...*/
IBOutlet id delegate;
BOOL doNotificationsOnMainThread;
BOOL recognizeLaterPlugins;
//Localized error messages
char localizedErrorCStrs[10][256];
char localizedUnknownErrorCStr[256];
IONotificationPortRef notifyPort; //Port for notifications from IOKit to mainThread
}
//Access to the shared instance of MyCameraCentral
+ (MyCameraCentral*) sharedCameraCentral;
//See if someone has requested (and therefore initialized) MyCameraCentral before
+ (BOOL) isCameraCentralExisting;
//Localization services - we may be in an external application so system services won't work dirctly. Make sure you have an an AutoreleasePool
+ (NSString*) localizedStringFor:(NSString*) str;
//The same for cstr stuff. This one makes an AutoreleasePool on its own